home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 12 / Amiga Format AFCD12 (Apr 1997, Issue 96).iso / -in_the_mag- / emulation / fs1541 / packet.c < prev    next >
C/C++ Source or Header  |  1997-02-09  |  26KB  |  1,132 lines

  1. /*
  2.     FS1541
  3.  
  4.     packet.c
  5.  
  6.  
  7.     This is the packet processor.
  8.  
  9.     If you are new to this subject and want to learn about it, you *must*
  10.     have the Amiga Guru Book next to you and compare the routines for each
  11.     packet with the specifications in the book -- then you will understand!
  12.  
  13. */
  14.  
  15. #include <string.h>
  16.  
  17. #include <exec/types.h>
  18. #include <exec/execbase.h>
  19. #include <exec/memory.h>
  20. #include <dos/dosextens.h>
  21. #include <dos/filehandler.h>
  22.  
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/utility.h>
  26.  
  27. #include "main.h"
  28. #include "packet.h"
  29. #include "support.h"
  30. #include "volume.h"
  31. #include "disk.h"
  32.  
  33. extern UBYTE diskinfo_image[840];
  34. extern struct BAM empty_bam;
  35.  
  36. static BOOL getfiledata(UBYTE entry, struct FHArg1 *fharg1);
  37. static BPTR trylockfile(LONG *err2, BSTR name, LONG access, struct FHArg1 *fharg1, BOOL allow_root);
  38.  
  39. static UBYTE fname1[20];
  40.  
  41. int inhibited = FALSE;
  42.  
  43. static LONG TestLock(struct FileLock *fl);
  44. static inline LONG TestLockRef(struct FileLock *fl);
  45.  
  46. /*-------------------------------------------------------------------------*/
  47.  
  48. void DoPackets(void)
  49. {
  50.     struct DosPacket *packet;
  51.  
  52.     while((packet = GetPacket(ourport)))
  53.     {
  54.         LONG error = DOSFALSE;
  55.         LONG err2 = 0;
  56.         BOOL f = TRUE;
  57.  
  58.         dpsender = packet->dp_Port;
  59.  
  60.         if(inhibited)
  61.         {
  62.             switch(packet->dp_Type)
  63.             {
  64.                 case ACTION_DISK_INFO:
  65.                 case ACTION_INHIBIT:
  66.                 case ACTION_FORMAT:
  67.                     break;
  68.  
  69.                 default:
  70.                     f = FALSE;
  71.                     err2 = ERROR_NOT_A_DOS_DISK;
  72.                     break;
  73.             }
  74.         }
  75.  
  76.         if(f) switch(packet->dp_Type)
  77.         {
  78.             case ACTION_LOCATE_OBJECT:
  79.             {
  80.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  81.                 struct FHArg1 fharg1;
  82.  
  83.                 if((err2 = TestLock(fl)))
  84.                     break;
  85.                 else if(!curvolumenode)
  86.                 {
  87.                     err2 = disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
  88.                     break;
  89.                 }
  90.  
  91.                 /* This FileSystem is easy since we don't have to take
  92.                    care of any FileLock path tracking and resolving */
  93.  
  94.                 error = trylockfile(&err2, packet->dp_Arg2, packet->dp_Arg3, &fharg1, TRUE);
  95.                 MotorOff();
  96.                 break;
  97.             }
  98.  
  99.             case ACTION_FREE_LOCK:
  100.             {
  101.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  102.  
  103.                 if(fl)
  104.                     freelock(fl);
  105.  
  106.                 MotorOff();
  107.                 error = DOSTRUE;
  108.                 break;
  109.             }
  110.  
  111.             case ACTION_COPY_DIR:
  112.             {
  113.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  114.  
  115.                 if(fl) {
  116.                     if(fl->fl_Access == EXCLUSIVE_LOCK) {
  117.                         /* Don't duplicate exclusive locks */
  118.                         err2 = ERROR_OBJECT_IN_USE;
  119.                     }
  120.                     else {
  121.                         if(fl->fl_Volume == MKBADDR(curdoslist)) {
  122.                             /* Try to duplicate it! */
  123.                             err2 = ERROR_NO_FREE_STORE;
  124.                             error = makelock(fl->fl_Key, SHARED_LOCK);
  125.                         }
  126.                         else {
  127.                             /* The reference disk is currently not inserted. */
  128.                             err2 = ERROR_DEVICE_NOT_MOUNTED;
  129.                         }
  130.                     }
  131.                 }
  132.                 else {
  133.                     if(curvolumenode) {
  134.                         /* Return shared lock on root directory */
  135.                         err2 = ERROR_NO_FREE_STORE;
  136.                         error = makelock(0, SHARED_LOCK);
  137.                     }
  138.                     else {
  139.                         err2 = ERROR_NO_DISK;
  140.                     }
  141.                 }
  142.  
  143.                 break;
  144.             }
  145.  
  146.             case ACTION_PARENT:
  147.             {
  148.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  149.  
  150.                 if(fl) {
  151.                     if(!(err2 = TestLockRef(fl))) {
  152.                         if(fl->fl_Key != 0) {
  153.                             /* Return shared lock on root directory */
  154.                             err2 = ERROR_NO_FREE_STORE;
  155.                             error = makelock(0, SHARED_LOCK);
  156.                         }
  157.                         else {
  158.                             err2 = 0;
  159.                         }
  160.                     }
  161.                 }
  162.                 else {
  163.                     err2 = 0;
  164.                 }
  165.  
  166.                 break;
  167.             }
  168.  
  169.             case ACTION_SAME_LOCK:
  170.             {
  171.                 struct FileLock *fl1 = BADDR(packet->dp_Arg1);
  172.                 struct FileLock *fl2 = BADDR(packet->dp_Arg2);
  173.  
  174.                 err2 = 0;
  175.  
  176.                 if(fl1 == fl2 || ((fl1->fl_Volume == fl2->fl_Volume) && (fl1->fl_Key == fl2->fl_Key)))
  177.                     error = DOSTRUE;
  178.  
  179.                 break;
  180.             }
  181.  
  182.             case ACTION_EXAMINE_OBJECT:
  183.             {
  184.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  185.                 struct FileInfoBlock *fib = BADDR(packet->dp_Arg2);
  186.  
  187.                 if(fl && fl->fl_Key != 0) {
  188.                     /* Examine file */
  189.                     struct FHArg1 fharg1;
  190.                     int entry;
  191.                     int special;
  192.  
  193.                     fib->fib_DiskKey = 0;
  194.                     fib->fib_DirEntryType = fib->fib_EntryType = ST_FILE;
  195.                     fib->fib_Protection = 0;
  196.                     fib->fib_Comment[0] = '\0';
  197.                     fib->fib_Date.ds_Days = 0;
  198.                     fib->fib_Date.ds_Minute = 0;
  199.                     fib->fib_Date.ds_Tick = 0;
  200.  
  201.                     if(fl->fl_Volume != MKBADDR(curdoslist)) {
  202.                         /* The reference disk is currently not inserted. */
  203.                         err2 = ERROR_DEVICE_NOT_MOUNTED;
  204.                         break;
  205.                     }
  206.  
  207.                     if((special = fl->fl_Key & FLKEY_SPECIALMASK)) {
  208.                         /* Examine virtual files */
  209.                         static struct { STRPTR s; ULONG l; } tbl[3] = {
  210.                             { VIRTUAL_FILE_D64, D64_SIZE },
  211.                             { VIRTUAL_FILE_DISKINFO, 840 },
  212.                             { VIRTUAL_FILE_OPT, 0 }
  213.                         };
  214.                         int index = (special>>FLKEY_SPECIALSHIFT)-2;
  215.  
  216.                         switch(special) {
  217.                             case FLKEY_DOLLAR:
  218.                                 strcpy(&fib->fib_FileName[1], VIRTUAL_FILE_DOLLAR);
  219.                                 fib->fib_FileName[0] = strlen(VIRTUAL_FILE_DOLLAR);
  220.                                 fib->fib_Size = curvolumenode->dollarlen;
  221.                                 error = DOSTRUE;
  222.                                 break;
  223.  
  224.                             case FLKEY_DISKINFO: case FLKEY_D64: case FLKEY_OPT:
  225.                                 strcpy(&fib->fib_FileName[1], tbl[index].s);
  226.                                 fib->fib_FileName[0] = strlen(tbl[index].s);
  227.                                 fib->fib_Size = tbl[index].l;
  228.                                 error = DOSTRUE;
  229.                                 break;
  230.  
  231.                             default:
  232.                                 err2 = ERROR_OBJECT_NOT_FOUND;
  233.                                 break;
  234.                         }
  235.                     }
  236.                     else {
  237.                         for(entry=0;entry<dirsize;entry++)
  238.                             if(fl->fl_Key == ((directory[entry].datat<<8)|directory[entry].datas))
  239.                                 break;
  240.     
  241.                         if(entry<dirsize) {
  242.                             if(getfiledata(entry, &fharg1)) {
  243.                                 copy64name(&fib->fib_FileName[1], directory[entry].name, 16);
  244.                                 fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
  245.                                 fib->fib_Size = fharg1.len;
  246.                                 error = DOSTRUE;
  247.                             }
  248.                             else err2 = ERROR_OBJECT_NOT_FOUND;
  249.                         }
  250.                         else err2 = ERROR_OBJECT_NOT_FOUND;
  251.                     }
  252.                 }
  253.                 else {
  254.                     /* Prepare for EXAMINE_NEXT, return volume name in
  255.                        fib_FileName */
  256.                     fib->fib_DiskKey = 0;
  257.                     fib->fib_DirEntryType = fib->fib_EntryType = ST_ROOT;
  258.                     strcpy(&fib->fib_FileName[1], &curvolumenode->name[1]);
  259.                     fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
  260.                     fib->fib_Protection = 0;
  261.                     fib->fib_Comment[0] = '\0';
  262.                     fib->fib_Date.ds_Days = 0;
  263.                     fib->fib_Date.ds_Minute = 0;
  264.                     fib->fib_Date.ds_Tick = 0;
  265.                     error = DOSTRUE;
  266.                 }
  267.  
  268.                 break;
  269.             }
  270.  
  271.             case ACTION_EXAMINE_NEXT:
  272.             {
  273.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  274.                 struct FileInfoBlock *fib = BADDR(packet->dp_Arg2);
  275.  
  276.                 if((err2 = TestLock(fl)))
  277.                     break;
  278.  
  279.                 fib->fib_DirEntryType = fib->fib_EntryType = ST_FILE;
  280.  
  281.                 err2 = ERROR_NO_MORE_ENTRIES;
  282.  
  283.                 while(fib->fib_DiskKey < dirsize) {
  284.                     int entry;
  285.                     struct FHArg1 fharg1;
  286.  
  287.                     entry = fib->fib_DiskKey++;
  288.  
  289.                     if(getfiledata(entry, &fharg1)) {
  290.                         copy64name(&fib->fib_FileName[1], directory[entry].name, 16);
  291.                         fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
  292.                         fib->fib_Size = fharg1.len;
  293.                         fib->fib_NumBlocks = fharg1.numblocks;
  294.                         error = DOSTRUE;
  295.                         break;
  296.                     }
  297.                 }
  298.  
  299.                 if(error == DOSFALSE)
  300.                     MotorOff();
  301.  
  302.                 break;
  303.             }
  304.  
  305.             case ACTION_FINDINPUT:
  306.             case ACTION_FINDOUTPUT:
  307.             case ACTION_FINDUPDATE:
  308.             {
  309.                 struct FileHandle *fh = BADDR(packet->dp_Arg1);
  310.                 struct FileLock *fl = BADDR(packet->dp_Arg2);
  311.                 struct FHArg1 *fharg1;
  312.                 LONG access = packet->dp_Type==ACTION_FINDINPUT ? SHARED_LOCK : EXCLUSIVE_LOCK;
  313.  
  314.                 if((err2 = TestLock(fl)))
  315.                     break;
  316.  
  317.                 if((fharg1 = AllocVec(sizeof(struct FHArg1), MEMF_ANY|MEMF_CLEAR))) {
  318.                     if(trylockfile(&err2, packet->dp_Arg3, access, fharg1, FALSE)) {
  319.                         if(fharg1->number!=NUM_VIRTUAL || access==SHARED_LOCK
  320.                         || (((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) == FLKEY_D64) {
  321.                             /* Allow virtual files only for reading, exception is $d64 */
  322.                             fh->fh_Arg1 = (LONG)fharg1;
  323.                             fh->fh_Port = DOSFALSE;
  324.                             error = DOSTRUE;
  325.                         }
  326.                         else {
  327.                             /* But new files with virtual file names can be created,
  328.                                 which will be real then. */
  329.                             freelock((struct FileLock*)BADDR(fharg1->lock));
  330.                             err2 = ERROR_OBJECT_NOT_FOUND;
  331.                         }
  332.                     }
  333.  
  334.                     if((error==DOSFALSE && access==EXCLUSIVE_LOCK && err2!=ERROR_INVALID_COMPONENT_NAME) || packet->dp_Type==ACTION_FINDOUTPUT) {
  335.                         if(!wprotected) {
  336.                             if(error==DOSFALSE) {
  337.                                 /* Create new file */
  338.                                 UWORD dblk;
  339.     
  340.                                 if(dirsize < 144) {
  341.                                     if((dblk = AllocBlock(18,0))) {
  342.                                         UBYTE clrblk[256];
  343.     
  344.                                         memset(&clrblk, 0, sizeof(clrblk));
  345.                                         clrblk[1] = 1;
  346.     
  347.                                         if(putblock_ts(dblk>>8, dblk&0xff, &clrblk)) {
  348.                                             struct DirEntry *de = &directory[dirsize++];
  349.     
  350.                                             memset(de, 0, sizeof(struct DirEntry));
  351.                                             de->type = 0x82; /* PRG, closed */
  352.                                             de->datat = dblk>>8;
  353.                                             de->datas = dblk&0xff;
  354.                                             de->lengthl = 1;
  355.                                             asciito64(de->name, fname1, 16);
  356.                                             StartUDSTimer();
  357.     
  358.                                             if(trylockfile(&err2, packet->dp_Arg3, access, fharg1, FALSE)) {
  359.                                                 fh->fh_Arg1 = (LONG)fharg1;
  360.                                                 fh->fh_Port = DOSFALSE;
  361.                                                 error = DOSTRUE;
  362.                                             }
  363.                                         }
  364.                                         else {
  365.                                             err2 = ABORT_DISK_ERROR;
  366.                                             FreeBlock(dblk>>8, dblk&0xff);
  367.                                         }
  368.                                     }
  369.                                     else err2 = ERROR_DISK_FULL;
  370.                                 }
  371.                                 else err2 = ERROR_DISK_FULL;
  372.                             }
  373.                             else if(fharg1->number != NUM_VIRTUAL) /* trying to overwrite $d64 */ {
  374.                                 /* Overwrite existing file */
  375.                                 struct DataBlock *block;
  376.                                 UBYTE t,s;
  377.                                 int i;
  378.     
  379.                                 for(i=0,t=fharg1->t,s=fharg1->s; t; t=block->t,s=block->s,i++) {
  380.                                     block = getblock_ts(t,s);
  381.                                     if(i>0) FreeBlock(t,s);
  382.                                 }
  383.                                 fharg1->len = 0;
  384.                                 fharg1->numblocks = 1;
  385.                                 block = getblock_ts(fharg1->t, fharg1->s);
  386.                                 block->t = 0;
  387.                                 block->s = 1;
  388.                                 putblock_ts(fharg1->t, fharg1->s, block);
  389.                             }
  390.                         }
  391.                         else err2 = ERROR_DISK_WRITE_PROTECTED;
  392.                     }
  393.                     else {
  394.                         if(error==DOSTRUE) {
  395.                             /* Open existing file, already done. */
  396.                         }
  397.                         /* else err2 still set from first trylockfile() call */
  398.                     }
  399.  
  400.                     if(error == DOSFALSE) {
  401.                         FreeVec(fharg1);
  402.                         MotorOff();
  403.                     }
  404.                 }
  405.                 else err2 = ERROR_NO_FREE_STORE;
  406.  
  407.                 break;
  408.             }
  409.  
  410.             case ACTION_READ:
  411.             {
  412.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  413.                 APTR buffer = (APTR)packet->dp_Arg2;
  414.                 ULONG togo = packet->dp_Arg3;
  415.                 struct DataBlock *block = NULL;
  416.  
  417.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
  418.                     break;
  419.  
  420.                 if(fharg1->pos + togo >= fharg1->len)
  421.                     togo = fharg1->len - fharg1->pos;
  422.  
  423.                 error = 0;
  424.  
  425.                 if(fharg1->number == NUM_VIRTUAL) {
  426.                     /* Handle virtual files */
  427.                     int special = ((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK;
  428.  
  429.                     switch(special) {
  430.                         case FLKEY_DOLLAR:
  431.                             CopyMem(&curvolumenode->dollarbuf[fharg1->pos], buffer, togo);
  432.                             fharg1->pos += togo;
  433.                             error += togo;
  434.                             break;
  435.  
  436.                         case FLKEY_DISKINFO:
  437.                             CopyMem(&diskinfo_image[fharg1->pos], buffer, togo);
  438.                             fharg1->pos += togo;
  439.                             error += togo;
  440.                             break;
  441.  
  442.                         case FLKEY_D64:
  443.                             while(togo) {
  444.                                 ULONG size, offset;
  445.  
  446.                                 if(!(block = getputblock((fharg1->pos)>>8, FALSE)))
  447.                                     break;
  448.  
  449.                                 offset = (fharg1->pos) & 255;
  450.  
  451.                                 size = 256 - offset;
  452.                                 if(togo < size)
  453.                                     size = togo;
  454.  
  455.                                 CopyMem(&((UBYTE*)block)[offset], buffer, size);
  456.  
  457.                                 buffer += size;
  458.                                 fharg1->pos += size;
  459.                                 error += size;
  460.                                 togo -= size;
  461.                             }
  462.                             break;
  463.  
  464.                         default:
  465.                             break;
  466.                     }
  467.                 }
  468.                 else {
  469.                     /* Handle real files */
  470.                     while(togo) {
  471.                         ULONG size;
  472.     
  473.                         if(fharg1->p == 254) {
  474.                             if(!block)
  475.                                 if(!(block = getblock_ts(fharg1->t, fharg1->s)))
  476.                                     break;
  477.                             fharg1->p = 0;
  478.                             fharg1->t = block->t;
  479.                             fharg1->s = block->s;
  480.                         }
  481.     
  482.                         size = 254 - fharg1->p;
  483.                         if(togo < size)
  484.                             size = togo;
  485.     
  486.                         if(!(block = getblock_ts(fharg1->t, fharg1->s)))
  487.                             break;
  488.     
  489.                         CopyMem(&block->data[fharg1->p], buffer, size);
  490.                         buffer += size;
  491.                         fharg1->p += size;
  492.                         fharg1->pos += size;
  493.                         error += size;
  494.                         togo -= size;
  495.                     }
  496.                 }
  497.  
  498.                 break;
  499.             }
  500.  
  501.             case ACTION_WRITE:
  502.             {
  503.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  504.                 APTR buffer = (APTR)packet->dp_Arg2;
  505.                 ULONG togo = packet->dp_Arg3;
  506.                 struct DataBlock *block = NULL;
  507.                 struct DataBlock newblk;
  508.  
  509.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
  510.                     break;
  511.  
  512.                 if(wprotected) {
  513.                     error = -1;
  514.                     err2 = ERROR_DISK_WRITE_PROTECTED;
  515.                     break;
  516.                 }
  517.  
  518.                 error = 0;
  519.  
  520.                 if((((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) == FLKEY_D64) {
  521.                     /* Handle writes to the $d64 file */
  522.                     if(fharg1->pos + togo >= D64_SIZE)
  523.                         togo = D64_SIZE - fharg1->pos;
  524.  
  525.                     while(togo) {
  526.                         ULONG size, offset;
  527.  
  528.                         if(!(block = getputblock((fharg1->pos)>>8, FALSE)))
  529.                             break;
  530.  
  531.                         offset = (fharg1->pos) & 255;
  532.  
  533.                         size = 256 - offset;
  534.                         if(togo < size)
  535.                             size = togo;
  536.  
  537.                         CopyMem(buffer, &((UBYTE*)block)[offset], size);
  538.                         getputblock((fharg1->pos)>>8, TRUE);
  539.  
  540.                         buffer += size;
  541.                         fharg1->pos += size;
  542.                         error += size;
  543.                         togo -= size;
  544.                     }
  545.                     break;
  546.                 }
  547.  
  548.                 while(togo) {
  549.                     ULONG size;
  550.  
  551.                     if(!block)
  552.                         block = getblock_ts(fharg1->t, fharg1->s);
  553.  
  554.                     if(fharg1->p == 254) {
  555.                         /* Switch to next block */
  556.                         if(!block->t) {
  557.                             /* Allocate new block */
  558.                             UWORD dblk;
  559.  
  560.                             if(!(dblk = AllocBlock(fharg1->t, fharg1->s))) {
  561.                                 err2 = ERROR_DISK_FULL;
  562.                                 break;
  563.                             }
  564.  
  565.                             fharg1->p = 0;
  566.                             block->t = dblk>>8;
  567.                             block->s = dblk&0xff;
  568.                             putblock_ts(fharg1->t, fharg1->s, block); /* link to previous block */
  569.                             fharg1->t = block->t;
  570.                             fharg1->s = block->s;
  571.                             fharg1->numblocks++;
  572.  
  573.                             block = &newblk;
  574.                             memset(&newblk, 0, sizeof(newblk));
  575.                             block->t = 0;
  576.                             block->s = 1;
  577.                         }
  578.                         else {
  579.                             /* Jump to existing next block */
  580.                             fharg1->p = 0;
  581.                             fharg1->t = block->t;
  582.                             fharg1->s = block->s;
  583.                             block = getblock_ts(fharg1->t, fharg1->s);
  584.                         }
  585.                     }
  586.  
  587.                     size = 254 - fharg1->p;
  588.                     if(togo < size)
  589.                         size = togo;
  590.  
  591.                     /* Insert data */
  592.                     CopyMem(buffer, &block->data[fharg1->p], size);
  593.                     buffer += size;
  594.  
  595.                     /* Advance block pointer and dump it */
  596.                     fharg1->p += size;
  597.                     if(!block->t)
  598.                         block->s = fharg1->p + 1;
  599.                     putblock_ts(fharg1->t, fharg1->s, block);
  600.  
  601.                     /* Adjust length field if necessary */
  602.                     fharg1->pos += size;
  603.                     if(fharg1->pos > fharg1->len)
  604.                         fharg1->len = fharg1->pos;
  605.  
  606.                     error += size;
  607.                     togo -= size;
  608.                 }
  609.  
  610.                 break;
  611.             }
  612.  
  613.             case ACTION_SEEK:
  614.             {
  615.                 struct FHArg1 fharg1bak, *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  616.                 LONG move = packet->dp_Arg2;
  617.  
  618.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
  619.                     break;
  620.  
  621.                 error = fharg1->pos;
  622.                 err2 = ERROR_SEEK_ERROR;
  623.  
  624.                 switch(packet->dp_Arg3) {
  625.                     case OFFSET_BEGINNING:
  626.                         move = move - error;
  627.                         break;
  628.  
  629.                     case OFFSET_CURRENT:
  630.                         break;
  631.  
  632.                     case OFFSET_END:
  633.                         move = move + fharg1->len - error;
  634.                         break;
  635.  
  636.                     default:
  637.                         error = -1;
  638.                         break;
  639.                 }
  640.  
  641.                 if(error != -1) {
  642.                     CopyMem(fharg1, &fharg1bak, sizeof(struct FHArg1));
  643.  
  644.                     if((error+move)<0 || (error+move)>fharg1->len)
  645.                         error = -1;
  646.                     else {
  647.                         if(((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) {
  648.                             /* Virtual files are easy */
  649.                             fharg1->pos += move;
  650.                         }
  651.                         else {
  652.                             if(move<0) {
  653.                                 /* When moving back, we have to rescan the whole file */
  654.                                 move = move + error;
  655.                                 fharg1->p = 0;
  656.                                 fharg1->pos = 0;
  657.                                 fharg1->t = fharg1->t0;
  658.                                 fharg1->s = fharg1->s0;
  659.                             }
  660.     
  661.                             while(move) {
  662.                                 ULONG size;
  663.                                 struct DataBlock *block;
  664.     
  665.                                 if(fharg1->p == 254) {
  666.                                     block = getblock_ts(fharg1->t, fharg1->s);
  667.  
  668.                                     if(!block) {
  669.                                         CopyMem(&fharg1bak, fharg1, sizeof(struct FHArg1));
  670.                                         error = -1;
  671.                                         err2 = ABORT_DISK_ERROR;
  672.                                         break;
  673.                                     }
  674.  
  675.                                     fharg1->p = 0;
  676.                                     fharg1->t = block->t;
  677.                                     fharg1->s = block->s;
  678.                                 }
  679.     
  680.                                 size = 254 - fharg1->p;
  681.             
  682.                                 if(move < size)
  683.                                     size = move;
  684.             
  685.                                 fharg1->p += size;
  686.                                 fharg1->pos += size;
  687.                                 move -= size;
  688.                             }
  689.                         }
  690.                     }
  691.                 }
  692.  
  693.                 break;
  694.             }
  695.  
  696.             case ACTION_END:
  697.             {
  698.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  699.  
  700.                 if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
  701.                     break;
  702.  
  703.                 if(fharg1->len != fharg1->len0) {
  704.                     /* File has been modified, update disk structure */
  705.                     int i;
  706.  
  707.                     for(i=0;i<dirsize;i++)
  708.                         if(directory[i].datat == fharg1->t0
  709.                         && directory[i].datas == fharg1->s0)
  710.                         {
  711.                             UWORD blks = fharg1->numblocks;
  712.                             directory[i].lengthl = blks&0xff;
  713.                             directory[i].lengthh = blks>>8;
  714.                             directory[i].type |= 0x80;
  715.                         }
  716.  
  717.                     StartUDSTimer();
  718.                 }
  719.  
  720.                 freelock(BADDR(fharg1->lock));
  721.                 FreeVec(fharg1);
  722.  
  723.                 error = DOSTRUE;
  724.                 break;
  725.             }
  726.  
  727.             case ACTION_IS_FILESYSTEM:
  728.                 /* Yes, we are. */
  729.                 error = DOSTRUE;
  730.                 break;
  731.  
  732.             case ACTION_CURRENT_VOLUME:
  733.             {
  734.                 struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
  735.  
  736.                 /* The packet name is somewhat misleading... */
  737.                 if(fharg1)
  738.                     error = ((struct FileLock*)BADDR(fharg1->lock))->fl_Volume;
  739.                 else {
  740.                     if(curvolumenode)
  741.                         error = (LONG)MKBADDR(curdoslist);
  742.                     else
  743.                         error = NULL;
  744.                 }
  745.  
  746.                 break;
  747.             }
  748.  
  749.             case ACTION_INFO:
  750.             case ACTION_DISK_INFO:
  751.             {
  752.                 struct InfoData *id;
  753.  
  754.                 if(packet->dp_Type == ACTION_INFO) {
  755.                     struct FileLock *fl = BADDR(packet->dp_Arg1);
  756.  
  757.                     if(fl && fl->fl_Volume != MKBADDR(curdoslist)) {
  758.                         /* The reference disk is currently not inserted. */
  759.                         err2 = ERROR_DEVICE_NOT_MOUNTED;
  760.                         break;
  761.                     }
  762.  
  763.                     id = BADDR(packet->dp_Arg2);
  764.                 }
  765.                 else {
  766.                     id = BADDR(packet->dp_Arg1);
  767.                 }
  768.  
  769.                 id->id_NumSoftErrors = numsofterrors;
  770.                 id->id_NumBlocks = 683;
  771.                 id->id_NumBlocksUsed = UsedBlocks();
  772.                 id->id_BytesPerBlock = 254;
  773.                 id->id_DiskState = wprotected ? ID_WRITE_PROTECTED : ID_VALIDATED;
  774.                 id->id_UnitNumber = fssm->fssm_Unit;
  775.  
  776.                 if(curvolumenode) {
  777.                     id->id_DiskType = ID_DOS_DISK;
  778.                     id->id_VolumeNode = MKBADDR(curdoslist);
  779.                     id->id_InUse = curvolumenode->locklist ? DOSTRUE : DOSFALSE;
  780.                 }
  781.                 else {
  782.                     #ifndef ID_BUSY /* My v40 header files don't */
  783.                     #define ID_BUSY 0x42555359
  784.                     #endif
  785.                     id->id_DiskType = inhibited ? ID_BUSY : disk_inserted ? ID_UNREADABLE_DISK : ID_NO_DISK_PRESENT;
  786.                 }
  787.  
  788.                 error = DOSTRUE;
  789.  
  790.                 break;
  791.             }
  792.  
  793.             case ACTION_INHIBIT:
  794.             {
  795.                 /* We could have trouble here if the DosList is locked,
  796.                    but then again, one shouldn't lock it for INHIBIT. */
  797.  
  798.                 if(packet->dp_Arg1 == DOSTRUE) {
  799.                     inhibited = TRUE;
  800.  
  801.                     StopUDSTimer();
  802.                     MotorOff();
  803.                     DoDiskRemove();
  804.                 }
  805.                 else {
  806.                     DoDiskInsert();
  807.  
  808.                     inhibited = FALSE;
  809.                 }
  810.  
  811.                 error = DOSTRUE;
  812.  
  813.                 break;
  814.             }
  815.  
  816.             case ACTION_CREATE_DIR:
  817.                 err2 = ERROR_INVALID_COMPONENT_NAME;
  818.                 break;
  819.  
  820.             case ACTION_DELETE_OBJECT:
  821.             {
  822.                 struct FileLock *fl = BADDR(packet->dp_Arg1);
  823.                 struct FHArg1 fharg1;
  824.  
  825.                 if((err2 = TestLock(fl)))
  826.                     break;
  827.  
  828.                 if(!wprotected) {
  829.                     if(trylockfile(&err2, packet->dp_Arg2, EXCLUSIVE_LOCK, &fharg1, FALSE)) {
  830.                         struct DataBlock *block;
  831.                         UBYTE t,s;
  832.     
  833.                         freelock((struct FileLock*)BADDR(fharg1.lock));
  834.     
  835.                         if(fharg1.number != NUM_VIRTUAL) {
  836.                             /* We do this only for non-virtual files. */
  837.                             for(t=fharg1.t,s=fharg1.s; t; t=block->t,s=block->s) {
  838.                                 block = getblock_ts(t,s);
  839.                                 FreeBlock(t,s);
  840.                             }
  841.         
  842.                             directory[fharg1.number].type = 0x00;
  843.                             StartUDSTimer();
  844.                             error = DOSTRUE;
  845.                         }
  846.                         else err2 = ERROR_DELETE_PROTECTED;
  847.                     }
  848.                 }
  849.                 else err2 = ERROR_DISK_WRITE_PROTECTED;
  850.  
  851.                 MotorOff();
  852.                 break;
  853.             }
  854.  
  855.             case ACTION_FORMAT:
  856.             {
  857.                 UBYTE buf[18];
  858.                 STRPTR a;
  859.                 struct DataBlock blk1;
  860.  
  861.                 ResetDisk();
  862.  
  863.                 if(!wprotected) {
  864.                     if((a = BADDR(packet->dp_Arg1))) {
  865.                         int l = a[0]>16 ? 16 : a[0];
  866.                         CopyMem(&a[1], buf, l);
  867.                         buf[l] = '\0';
  868.                     }
  869.                     else buf[0] = '\0';
  870.  
  871.                     asciito64(empty_bam.name, buf, 16);
  872.                     putblock_ts(18,0,&empty_bam);
  873.                     memset(&blk1, 0, sizeof(blk1));
  874.                     blk1.s = 0xff;
  875.                     putblock_ts(18,1,&blk1);
  876.  
  877.                     error = DOSTRUE;
  878.                 }
  879.                 else err2 = ERROR_DISK_WRITE_PROTECTED;
  880.  
  881.                 break;
  882.             }
  883.  
  884.             case ACTION_RENAME_DISK:
  885.             {
  886.                 UBYTE buf[18];
  887.                 STRPTR a;
  888.  
  889.                 if(curvolumenode) {
  890.                     if(!wprotected) {
  891.                         if((a = BADDR(packet->dp_Arg1))) {
  892.                             int l = a[0]>16 ? 16 : a[0];
  893.                             CopyMem(&a[1], buf, l);
  894.                             buf[l] = '\0';
  895.                         }
  896.                         else buf[0] = '\0';
  897.  
  898.                         asciito64(bam->name, buf, 16);
  899.  
  900.                         while(!AttemptLockDosList(LDF_VOLUMES|LDF_WRITE))
  901.                             DoPackets();
  902.                         copy64name(&curvolumenode->name[1], bam->name, 16);
  903.                         curvolumenode->name[0] = strlen(&curvolumenode->name[1]);
  904.                         UnLockDosList(LDF_VOLUMES|LDF_WRITE);
  905.  
  906.                         StartUDSTimer();
  907.  
  908.                         error = DOSTRUE;
  909.                     }
  910.                     else err2 = ERROR_DISK_WRITE_PROTECTED;
  911.                 }
  912.                 else err2 = disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
  913.  
  914.                 break;
  915.             }
  916.  
  917.             case ACTION_RENAME_OBJECT:
  918.             {
  919.                 struct FileLock *fl1 = BADDR(packet->dp_Arg1),
  920.                                 *fl2 = BADDR(packet->dp_Arg3);
  921.                 struct FHArg1 fharg1;
  922.  
  923.                 if(!((err2 = TestLock(fl1)) || (err2 = TestLock(fl2)))) {
  924.                     if(!wprotected) {
  925.                         if(trylockfile(&err2, packet->dp_Arg2, SHARED_LOCK, &fharg1, FALSE)) {
  926.                             freelock((struct FileLock*)BADDR(fharg1.lock));
  927.  
  928.                             if(fharg1.number != NUM_VIRTUAL) {
  929.                                 STRPTR a;
  930.                                 UBYTE buf[256];
  931.  
  932.                                 if((a = BADDR(packet->dp_Arg4))) {
  933.                                     CopyMem(&a[1], buf, a[0]);
  934.                                     buf[a[0]] = '\0';
  935.  
  936.                                     if(!strchr(buf, '/')) {
  937.                                         a = strchr(buf, ':');
  938.                                         strncpy(fname1, a ? a+1 : buf, 17);
  939.                                         fname1[16] = '\0';
  940.  
  941.                                         asciito64(directory[fharg1.number].name, fname1, 16);
  942.                                         StartUDSTimer();
  943.                                         error = DOSTRUE;
  944.                                     }
  945.                                     else err2 = ERROR_INVALID_COMPONENT_NAME;
  946.                                 }
  947.                                 else err2 = ERROR_INVALID_COMPONENT_NAME;
  948.                             }
  949.                             else err2 = ERROR_OBJECT_NOT_FOUND;
  950.                         }
  951.                     }
  952.                     else err2 = ERROR_DISK_WRITE_PROTECTED;
  953.                 }
  954.  
  955.                 break;
  956.             }
  957.  
  958.             case ACTION_SET_FILE_SIZE:
  959.                 error = -1;
  960.                 err2 = ERROR_ACTION_NOT_KNOWN;
  961.                 break;
  962.  
  963.             default:
  964.                 err2 = ERROR_ACTION_NOT_KNOWN;
  965.                 break;
  966.         }
  967.     
  968.         ReturnPacket(packet, error, err2);
  969.     }
  970. }
  971.  
  972. static LONG TestLock(struct FileLock *fl)
  973. {
  974.     if(fl) {
  975.         if(fl->fl_Volume != MKBADDR(curdoslist))
  976.             /* The reference disk is currently not inserted. */
  977.             return(ERROR_DEVICE_NOT_MOUNTED);
  978.         if(fl->fl_Key != 0)
  979.             /* An invalid lock has been passed. */
  980.             return(ERROR_OBJECT_WRONG_TYPE);
  981.     }
  982.     return(0);
  983. }
  984.  
  985. static inline LONG TestLockRef(struct FileLock *fl)
  986. {
  987.     if(fl->fl_Volume != MKBADDR(curdoslist))
  988.         /* The reference disk is currently not inserted. */
  989.         return(ERROR_DEVICE_NOT_MOUNTED);
  990.     return(0);
  991. }
  992.  
  993. /*-------------------------------------------------------------------------*/
  994.  
  995. static BOOL getfiledata(UBYTE entry, struct FHArg1 *fharg1)
  996. {
  997.     if(directory[entry].name[0] != 0xa0) {
  998.         UWORD type = (directory[entry].type) & 0x7;
  999.  
  1000.         if(type!=0x00) { // anything but DEL-Files
  1001.             struct DataBlock *block;
  1002.             int i,t,s,size;
  1003.  
  1004.             for(i=0,t=directory[entry].datat,s=directory[entry].datas,size=0;
  1005.                 i<683; /* a primitive solution to overcome circular links */
  1006.                 t=block->t,s=block->s,i++)
  1007.             {
  1008.                 if(!(block = getblock_ts(t,s)))
  1009.                     return(FALSE);
  1010.  
  1011.                 if(block->t)
  1012.                     size+=254;
  1013.                 else {
  1014.                     size+=block->s-1;
  1015.                     break;
  1016.                 }
  1017.             }
  1018.  
  1019.             if(i<683) {
  1020.                 fharg1->len = fharg1->len0 = size;
  1021.                 fharg1->numblocks = i+1;
  1022.                 fharg1->t = fharg1->t0 = directory[entry].datat;
  1023.                 fharg1->s = fharg1->s0 = directory[entry].datas;
  1024.                 fharg1->number = entry;
  1025.                 return(TRUE);
  1026.             }
  1027.         }
  1028.     }
  1029.  
  1030.     return(FALSE);
  1031. }
  1032.  
  1033. /*-------------------------------------------------------------------------*/
  1034.  
  1035. /* May only be called if curvolumenode is valid! */
  1036. static BPTR trylockfile(LONG *err2, BSTR name, LONG access, struct FHArg1 *fharg1, BOOL allow_root)
  1037. {
  1038.     UBYTE buf[256];
  1039.     STRPTR a;
  1040.     LONG error;
  1041.  
  1042.     error = DOSFALSE;
  1043.  
  1044.     /* Convert BSTR argument into C string */
  1045.     if((a = BADDR(name))) {
  1046.         CopyMem(&a[1], buf, a[0]);
  1047.         buf[a[0]] = '\0';
  1048.  
  1049.         if(strchr(buf, '/')) {
  1050.             /* User tries to access subdirectories */
  1051.             *err2 = ERROR_INVALID_COMPONENT_NAME;
  1052.             return(error);
  1053.         }
  1054.  
  1055.         a = strchr(buf, ':');
  1056.         strncpy(fname1, a ? a+1 : buf, 17);
  1057.         fname1[16] = '\0';
  1058.     }
  1059.     else
  1060.         fname1[0] = '\0';
  1061.  
  1062.     if(fname1[0] == '\0') {
  1063.         if(allow_root) {
  1064.             /* Return lock on root directory */
  1065.             if(access == EXCLUSIVE_LOCK) {
  1066.                 *err2 = ERROR_OBJECT_IN_USE;
  1067.             }
  1068.             else {
  1069.                 *err2 = ERROR_NO_FREE_STORE;
  1070.                 error = makelock(0, access);
  1071.             }
  1072.         }
  1073.         else *err2 = ERROR_OBJECT_WRONG_TYPE;
  1074.     }
  1075.     else {
  1076.         int entry;
  1077.  
  1078.         *err2 = ERROR_OBJECT_NOT_FOUND;
  1079.  
  1080.         /* Look up file in directory and lock it */
  1081.         for(entry=0;entry<dirsize;entry++) {
  1082.             copy64name(buf, directory[entry].name, 16);
  1083.             if(!Stricmp(buf, fname1))
  1084.                 break;
  1085.         }
  1086.  
  1087.         if(entry == dirsize) {
  1088.             /* Perhaps we can provide a virtual file */
  1089.             fharg1->number = NUM_VIRTUAL;
  1090.  
  1091.             if(!Stricmp(VIRTUAL_FILE_DISKINFO,fname1)) {
  1092.                 *err2 = ERROR_NO_FREE_STORE;
  1093.                 error = fharg1->lock = makelock(FLKEY_DISKINFO, access);
  1094.                 fharg1->len = fharg1->len0 = 840;
  1095.             }
  1096.             else if(fname1[0] == '$') {
  1097.                 if(!Stricmp(VIRTUAL_FILE_DOLLAR,fname1)) {
  1098.                     *err2 = ERROR_NO_FREE_STORE;
  1099.                     error = fharg1->lock = makelock(FLKEY_DOLLAR, access);
  1100.                     fharg1->len = fharg1->len0 = curvolumenode->dollarlen;
  1101.                 }
  1102.                 else if(!Stricmp(VIRTUAL_FILE_D64,fname1)) {
  1103.                     *err2 = ERROR_NO_FREE_STORE;
  1104.                     error = fharg1->lock = makelock(FLKEY_D64, access);
  1105.                     fharg1->len = fharg1->len0 = D64_SIZE;
  1106.                 }
  1107.                 else if(!Stricmp(VIRTUAL_FILE_OPT,fname1)) {
  1108.                     if(!wprotected) {
  1109.                         *err2 = ERROR_NO_FREE_STORE;
  1110.                         error = fharg1->lock = makelock(FLKEY_OPT, access);
  1111.                         fharg1->len = fharg1->len0 = 0;
  1112.                         OptimizeDirectory();
  1113.                         StartUDSTimer();
  1114.                     }
  1115.                     else *err2 = ERROR_DISK_WRITE_PROTECTED;
  1116.                 }
  1117.             }
  1118.         }
  1119.         else {
  1120.             if(getfiledata(entry, fharg1)) {
  1121.                 if(lockable(fharg1->t, fharg1->s, access)) {
  1122.                     *err2 = ERROR_NO_FREE_STORE;
  1123.                     error = fharg1->lock = makelock(((fharg1->t)<<8)|fharg1->s, access);
  1124.                 }
  1125.                 else *err2 = ERROR_OBJECT_IN_USE;
  1126.             }
  1127.         }
  1128.     }
  1129.  
  1130.     return(error);
  1131. }
  1132.